package com.chatsimple.netty

import com.chatsimple.logDebug
import com.chatsimple.netty.task.ITaskHandler
import com.ly.data.MessageProtobuf.TaskProto
import io.netty.channel.Channel
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInboundHandlerAdapter
import java.lang.ref.WeakReference
import java.util.concurrent.ConcurrentHashMap

class ServerReadHandler(vararg handler: ITaskHandler) : ChannelInboundHandlerAdapter() {
    private val mTaskHandlers = listOf(*handler)

    override fun channelActive(ctx: ChannelHandlerContext) {
        super.channelActive(ctx)
        ctx.channel().apply {
            clientContainer[id().asLongText()] = WeakReference(this)
        }
        logDebug("客户端(${ctx.channel().remoteAddress()}) 连接成功，客户端数量 = ${clientContainer.size}")
    }

    override fun channelInactive(ctx: ChannelHandlerContext) {
        super.channelInactive(ctx)
        ctx.channel().apply {
            clientContainer.remove(id().asLongText())
            mTaskHandlers.forEach {
                it.destroy(this)
            }
        }
        logDebug("客户端(${ctx.channel().remoteAddress()}) 断开连接")
    }

    @Deprecated(
        "Deprecated in Java",
        ReplaceWith("super.exceptionCaught(ctx, cause)", "io.netty.channel.ChannelInboundHandlerAdapter")
    )
    override fun exceptionCaught(ctx: ChannelHandlerContext?, cause: Throwable?) {
        super.exceptionCaught(ctx, cause)
        ctx?.channel()?.apply {
            clientContainer.remove(id().asLongText())
            mTaskHandlers.forEach {
                it.destroy(this)
            }
        }
        logDebug("客户端(${ctx?.channel()?.remoteAddress()}) 异常断开连接 case:$cause")
    }

    override fun channelRead(ctx: ChannelHandlerContext, task: Any) {
        super.channelRead(ctx, task)
        logDebug("客户端(${ctx.channel().remoteAddress()}) 请求:$task")
        //先直接转发给客户端
        if (task !is TaskProto) return
        mTaskHandlers.forEach {
            it.handle(ctx.channel(), task)
        }
    }

    companion object {
        val clientContainer = ConcurrentHashMap<String, WeakReference<Channel>>()
    }
}